#include <stdio.h>
#include <stdlib.h>
#include "NandFlash.h"

#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "NandFlash.h"

static const char *TAG = "Nand-Memory";
#define MAX_CHAR_SIZE    256
#define MOUNT_POINT "/sdcard"
#define MAX_FILE_NUMBER  20

//#define PIN_NUM_MISO  13
//#define PIN_NUM_MOSI  11
//#define PIN_NUM_CLK   12
//#define PIN_NUM_CS    10


#define PIN_NUM_MISO  19
#define PIN_NUM_MOSI  23
#define PIN_NUM_CLK   18
#define PIN_NUM_CS    28

/*******************************************************************************/
esp_err_t Empty_File(void) {
     int i;
     char filename[100];
     FILE *fp;

     for ( i = 0 ; i < MAX_FILE_NUMBER ; i++) {
        sprintf(filename , "/sdcard/zlog_%d.txt" , i);
        fp = fopen( filename , "r");
        if (fp == NULL) break;
        fclose(fp);
     }
     
    if (i < 10 ) return ESP_FAIL;

    for ( i = 0 ; i < MAX_FILE_NUMBER ; i++) {
        sprintf(filename , "/sdcard/zlog_%d.txt" , i);
        fp = fopen( filename , "w");
        if (fp != NULL) fclose(fp);
     }

    return ESP_OK;
}

/*******************************************************************************/
esp_err_t Nand_open_file( FILE *fp) {
    int i;
    struct stat st;
    char filename[100];

    for ( i = 0 ; i < MAX_FILE_NUMBER ; i++) {
        sprintf( filename ,"/sdcard/zlog_%d.txt" , i);
        if (stat("/sdcard/zlog_1.txt", &st) == 0) {
            if ( st.st_size < 10 * 1024 * 1024) {
               fp = fopen(filename , "a+");
               if (fp == NULL) return ESP_FAIL;
               return ESP_OK;
            }
        } else return ESP_FAIL;
    }

     return ESP_FAIL;
}

/*******************************************************************************/
size_t Nand_write_file( const char *data )
{
    char s_tmp[MAX_CHAR_SIZE + 10];
    size_t write_size;

    FILE *fp = fopen( "/sdcard/zlog_1.txt" , "a+");

    if (strlen(data) > MAX_CHAR_SIZE || fp == NULL) return ESP_FAIL;

    sprintf(s_tmp , "%s\n" , data);
   
    write_size = fwrite(data , 1 , strlen(s_tmp) , fp);
    return write_size;
}

/*******************************************************************************/

esp_err_t Nand_read_file( )
{
    
   
      return ESP_OK;
}

/*************************************************************************************************** */

esp_err_t Init_NandFlash() {
    esp_err_t ret;
    
    spi_bus_config_t bus_cfg = {
        .mosi_io_num = PIN_NUM_MOSI,
        .miso_io_num = PIN_NUM_MISO,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 20000000,
    };

    ret = spi_bus_initialize( SPI2_HOST , &bus_cfg, SDSPI_DEFAULT_DMA);
  
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = false,
        .max_files = MAX_FILE_NUMBER,
        .allocation_unit_size = 11 * 1024 *1024
    };

    sdmmc_card_t *card;

    const char mount_point[] = MOUNT_POINT;
     
    ESP_LOGE(TAG, "Initializing SD card ...");

    sdmmc_host_t host = SDSPI_HOST_DEFAULT();
   
    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs = PIN_NUM_CS;
    slot_config.host_id = host.slot;

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                     "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
        } else {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                     "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
        }
        return ret;
    } else   ESP_LOGI(TAG, "Filesystem mounted");
    
    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
    
    return ESP_OK;
}

